package de.metalcon.gwt.server.modules;

import java.util.HashMap;
import java.util.Map;

import javax.servlet.ServletContext;

import org.neo4j.graphdb.Direction;
import org.neo4j.graphdb.DynamicRelationshipType;
import org.neo4j.graphdb.GraphDatabaseService;
import org.neo4j.graphdb.Node;
import org.neo4j.graphdb.Relationship;
import org.neo4j.graphdb.ReturnableEvaluator;
import org.neo4j.graphdb.StopEvaluator;
import org.neo4j.graphdb.Transaction;
import org.neo4j.graphdb.Traverser;
import org.neo4j.graphdb.Traverser.Order;
import org.neo4j.graphdb.index.Index;
import org.neo4j.graphdb.index.IndexManager;

import de.metalcon.gwt.server.ContextListener;
import de.metalcon.gwt.server.db.ANode;
import de.metalcon.gwt.server.db.Relations;
import de.metalcon.gwt.shared.ContentTransmitter;

public class StreamModuleServer extends AModuleServer {

	public StreamModuleServer(HashMap<String, Object> requestVars, ServletContext context) {
		super(requestVars, context);
	}

	@Override
	public ContentTransmitter getTransmitter() {
		ContentTransmitter t = new ContentTransmitter();

		String type = (String) requestVars.get("type");

		for (Map.Entry<String, Object> entry : requestVars.entrySet()) {
			t.setString(entry.getKey(), (String) entry.getValue());

		}

		final GraphDatabaseService db = ContextListener.getNeo4JInstance(context);
		IndexManager index = db.index();

		if (type.equals("user")) {
			Index<Node> user = index.forNodes(type);
			Node u = user.get("email", (String) requestVars.get("key")).getSingle();
			// t.setString("email", (String) u.getProperty("email"));
			if (u != null) {
				for (Relationship rel : u.getRelationships(DynamicRelationshipType.withName("BANDUSER"))) {
					Node b = rel.getOtherNode(u);
					// Node[] simBands = CalculateSimilarBands(b);
					ContentTransmitter band = new ContentTransmitter();
					band.setString("key", (String) b.getProperty("key"));
					band.setString("mid", "MID:" + (String) b.getProperty("key"));
					int cnt = 0;
					for (Relationship r : b.getRelationships(DynamicRelationshipType.withName("BANDUSER"))) {
						cnt++;
					}
					band.setString("fans", "" + cnt);
					t.addListElement("band", band);
					// t.setString((String) b.getProperty("key"), (String)
					// b.getProperty("key"));
				}
			} else {
				t.addError("User not found!");
			}
		} else if (type.equals("band")) {
			Index<Node> band = index.forNodes(type);
			Node b = band.get("key", (String) requestVars.get("key")).getSingle();
			// t.setString("email", (String) u.getProperty("email"));

			for (Relationship rel : b.getRelationships(DynamicRelationshipType.withName("BANDUSER"))) {
				Node u = rel.getOtherNode(b);
				ContentTransmitter user = new ContentTransmitter();
				user.setString("key", (String) u.getProperty("email"));
				user.setString("mid", "MID:" + (String) u.getProperty("email"));

				int cnt = 0;
				for (Relationship r : u.getRelationships(DynamicRelationshipType.withName("BANDUSER"))) {
					cnt++;
				}
				user.setString("bands", "" + cnt);

				t.addListElement("user", user);
				// t.setString((String) b.getProperty("key"), (String)
				// b.getProperty("key"));
			}
		}

		else if (type.equals("city")) {
			t.setString("coming", "soon");
		}

		return t;
	}

	private Node[] CalculateSimilarBands(Node b) {
		String bkey = (String) b.getProperty("key");
		HashMap<String, Integer> map = new HashMap<String, Integer>();
		Traverser users = b.traverse(Order.BREADTH_FIRST, StopEvaluator.DEPTH_ONE, ReturnableEvaluator.ALL_BUT_START_NODE,
				DynamicRelationshipType.withName("BANDUSER"), Direction.BOTH);
		for (Node u : users) {
			Traverser sim = u.traverse(Order.BREADTH_FIRST, StopEvaluator.DEPTH_ONE, ReturnableEvaluator.ALL_BUT_START_NODE,
					DynamicRelationshipType.withName("BANDUSER"), Direction.BOTH);
			for (Node band : sim) {
				String key = (String) band.getProperty("key");
				if (key.equals(bkey))
					continue;
				if (map.get(key) != null)
					map.put(key, (Integer) map.get(key) + 1);
				else
					map.put(key, 1);
			}
		}

		Integer m1 = 0, m2 = 0, m3 = 0, tmp = 0;
		String k1 = "", k2 = "", k3 = "";
		for (String k : map.keySet()) {
			tmp = map.get(k);
			if (tmp > m1) {
				m3 = m2;
				m2 = m1;
				m1 = tmp;
				k3 = k2;
				k2 = k1;
				k1 = k;
			} else if (tmp > m2) {
				m3 = m2;
				m2 = tmp;
				k3 = k2;
				k2 = k;
			} else if (tmp > m3) {
				m3 = tmp;
				k3 = k;
			}

		}
		final GraphDatabaseService db = ContextListener.getNeo4JInstance(context);
		IndexManager index = db.index();
		Index bands = index.forNodes("band");
		Node n1 = (Node) bands.get("key", k1).getSingle();
		Node n2 = (Node) bands.get("key", k2).getSingle();
		Node n3 = (Node) bands.get("key", k3).getSingle();
		Node[] res = { n1, n2, n3 };
		return res;
	}

}
